from pickle import FALSE
from re import S
from statistics import median
from tkinter import EXCEPTION
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.font_manager import FontProperties
import ast  
datapath="D:/data/chainTPN"

#ANCHOR -- basic function 
def filter_data(df,chosen_dict):
    new_df=df.copy() 
    for attri,orgs in chosen_dict.items():
        if isinstance(orgs,list) or isinstance(orgs,np.ndarray):
            new_df=new_df[new_df[attri].isin(orgs)]
        else:
            new_df=new_df[new_df[attri]==orgs] 
    return new_df
def check_ax_detail(ax,ax_label,xlabel,ylabel,yticks,yscale,yticklabels,ylim,xticks,xscale,xticklabels,xlim,base_fontsize,label_loc=[-0.15,1.05],ylabelpad=0,xlabelpad=0):
    if yscale=="log":
        ax.set_yscale("log")
    if xscale=="log":
        ax.set_xscale("log")
    label_size=1.5
    if xlabelpad!=0:
        ax.set_xlabel(xlabel,fontsize=base_fontsize-label_size,labelpad=xlabelpad)
    else:
        ax.set_xlabel(xlabel,fontsize=base_fontsize-label_size)
    if len(ylabel)>0:
        if ylabelpad!=0:
            ax.set_ylabel(ylabel,fontsize=base_fontsize-label_size,labelpad=ylabelpad)
        else:
            ax.set_ylabel(ylabel,fontsize=base_fontsize-label_size)
    else:
        ax.set_ylabel(ylabel)
    if len(ylim)>0:
        ax.set_ylim(*ylim)
    if len(xlim)>0:
        ax.set_xlim(*xlim)
    if len(yticks)>0:
        ax.set_yticks(yticks)
    if len(xticks)>0:
        ax.set_xticks(xticks)
    if len(yticklabels)>0:
        ax.set_yticklabels(yticklabels,fontsize=base_fontsize-4)
    if len(xticklabels)>0:
        ax.set_xticklabels(xticklabels,fontsize=base_fontsize-4)
    #ax label
    if len(ax_label)>0:
        # ax_font=FontProperties(family='Arial',weight='bold')
        ax_font=FontProperties(family='Arial')
        ax.text(label_loc[0],label_loc[1],ax_label,fontsize=base_fontsize+1.5,fontproperties=ax_font,transform=ax.transAxes,va='top',ha='left')
def get_list(ls):
    n_ls=[]
    for row in ls:
        row=str(row)
        row=row.strip('[]')
        row=row.replace('array([','')
        row=row.replace('])','')
        row=row.split(',')
        row=list(map(float,row))
        n_ls.append(row)
    return np.array(n_ls)
 
#ANCHOR -- correlated 
def plot_corr_MAE_1(ax,ax_label,filename,chosen_dict,method_list,label_list,xname,xlabel,ylabel,colors,markersize,base_fontsize,yscale,yticks=[],yticklabels=[],ylim=[],xticks=[],xticklabels=[],xlim=[],xscale="abs",ylabelpad=0,legend=False,ncol=1,markeredgewidth=0.5,error="abs",xlabelpad=0,label_loc=[-0.15, 1.05],show_errorbar=True,errorbar_type='se',errorbar_capsize=3,errorbar_linewidth=1.5,errorbar_alpha=1,subfigure=False,subylim=[],subxlim=[],sub_xticks=[],sub_xticklabel=[],sub_yticks=[],sub_yticklabel=[],sub_loc=[],sub_ylabel="",sub_x_list=[],alpha=0.8): 
    df=pd.read_csv(filename,on_bad_lines='skip')
    if len(chosen_dict)>0:
        df=filter_data(df,chosen_dict)
    if error=="abs": 
        for method in method_list:
            df[method]=np.abs(df["ideal"]-df[method])
    else: 
        for method in method_list:
            df[method]=np.log(np.abs(df["ideal"]-df[method])/np.abs(df["ideal"])+1)
    grouped=df.groupby(xname)
    xx=[]
    yy=[]
    yyee=[]
    for i, method in enumerate(method_list):
        x_values=[]
        y_means=[]
        y_errors=[]
        
        for group_name,group_data in grouped:
            values=group_data[method].dropna()
            if len(values)>0:
                x_values.append(group_name)
                y_means.append(values.mean())
                if len(values)>1:
                    if errorbar_type=='std':
                        y_errors.append(values.std())
                    else:
                        y_errors.append(values.std()*2/np.sqrt(len(values)))
                else:
                    y_errors.append(0)
        if len(x_values)==0:
            print(f"Warning: No data for method {method} after filtering!")
            continue

        sorted_idx=np.argsort(x_values)
        x_sorted=np.array(x_values)[sorted_idx]
        y_means_sorted=np.array(y_means)[sorted_idx]
        y_errors_sorted=np.array(y_errors)[sorted_idx] if y_errors else None
        xx.append(x_sorted)
        yy.append(y_means_sorted)
        yyee.append(y_errors_sorted) 
        
        if show_errorbar and y_errors_sorted is not None and len(y_errors_sorted)>0:
            ax.errorbar(x_sorted,y_means_sorted,yerr=y_errors_sorted,fmt='-o',ecolor=colors[method],elinewidth=errorbar_linewidth,capsize=errorbar_capsize,alpha=alpha,color=colors[method],label=label_list[i],markersize=markersize,markeredgewidth=markeredgewidth,markeredgecolor='white')
        else:
            ax.plot(x_sorted,y_means_sorted,'-o',color=colors[method],label=label_list[i],markersize=markersize,markeredgewidth=markeredgewidth,markeredgecolor='white',alpha=alpha)
    

    if legend:
        ax.legend(ncol=ncol,prop={'size':base_fontsize-3.5})
    if subfigure:
        axins=ax.inset_axes(sub_loc) 
        for i, method in enumerate(method_list):
            axins.errorbar(xx[i][sub_x_list[0]:sub_x_list[1]],yy[i][sub_x_list[0]:sub_x_list[1]],yerr=yyee[i][sub_x_list[0]:sub_x_list[1]],fmt='-o',ecolor=colors[method],elinewidth=errorbar_linewidth,capsize=errorbar_capsize,alpha=errorbar_alpha,color=colors[method],label=label_list[i],markersize=markersize,markeredgewidth=markeredgewidth,markeredgecolor='white')
        
        axins.set_yscale("log")
        axins.set_xticks(sub_xticks)
        axins.set_xticklabels(sub_xticklabel,fontsize=base_fontsize-5.5)
        axins.set_yticks(sub_yticks)
        axins.set_yticklabels(sub_yticklabel,fontsize=base_fontsize-5.5)
        axins.set_ylim(*subylim)
        axins.set_xlim(*subxlim)
        axins.set_ylabel(sub_ylabel,fontsize=base_fontsize-4.5)
    check_ax_detail(ax,ax_label,xlabel,ylabel,yticks,yscale,yticklabels,ylim,xticks,xscale,xticklabels,xlim,base_fontsize,ylabelpad=ylabelpad,xlabelpad=xlabelpad,label_loc=label_loc)

def plot_corr_bar_1(ax,ax_label,filename,chosen_dict,method_list,xlabel,ylabel,colors,base_fontsize,yscale,yticks=[],yticklabels=[],ylim=[],xticks=[],xticklabels=[],xlim=[],xscale="abs",ylabelpad=0,legend=False,ncol=1,error="abs",bar_alpha=0.7,width=0.3,hatch_patterns=['','//'],ri_col='ri',gap=0.1,label_loc=[-0.15,1.05],errorbar=True,error_type='se',error_capsize=2,error_linewidth=2,error_color='gray',error_alpha=1):  
    df=pd.read_csv(filename,on_bad_lines='skip')
    if len(chosen_dict)>0:
        df=filter_data(df,chosen_dict)
    if error=="abs": 
        for method in method_list:
            df[method]=np.abs(df["ideal"]-df[method])
    else: 
        for method in method_list:
            df[method]=np.log(np.abs(df["ideal"]-df[method])/np.abs(df["ideal"])+1)
    colors=[colors[method] for method in method_list]
    ri_values=sorted(df[ri_col].unique())
    num_ri=len(ri_values)
    num_methods=len(method_list)
    
    df_list=[]
    for name in method_list:
        for ri_val in ri_values:
            subset=df[df[ri_col]==ri_val]
            size=len(subset)
            if size>0:
                df_list.append(pd.DataFrame({
                    "method":[name]*size,
                    "value":subset[name].values,
                    "ri":[ri_val]*size
                }))
    
    df_new=pd.concat(df_list,ignore_index=True) if df_list else pd.DataFrame()
    if df_new.empty:
        print("Warning: No data after filtering!")
        return ax
    
    positions=np.arange(num_methods)
    bar_width=width/num_ri
    gap_width=gap*bar_width
    legend_handles=[]
    
    for ri_idx,ri_val in enumerate(ri_values):
        ri_data=df_new[df_new["ri"]==ri_val]
        offset=ri_idx*(bar_width+gap_width)-(width+(num_ri-1)*gap_width)/2+bar_width/2
        x_positions=positions+offset
        
        means=[]
        errors=[] 
        
        for method in method_list:
            method_data=ri_data[ri_data["method"]==method]["value"]
            if not method_data.empty:
                mean_val=method_data.mean()
                std_val=method_data.std()
                n=len(method_data)
                if error_type=='se': 
                    error_val=std_val*2/np.sqrt(n) if n > 0 else 0
                else:
                    error_val=std_val
                means.append(mean_val)
                errors.append(error_val)
            else:
                means.append(0)
                errors.append(0)
        bars=ax.bar(x_positions,means,width=bar_width,color=colors,alpha=bar_alpha,edgecolor="white",hatch=hatch_patterns[ri_idx],label=f'ri={ri_val}')
        if errorbar:
            ax.errorbar(x_positions,means,yerr=errors,fmt='none',ecolor=error_color,elinewidth=error_linewidth,capsize=error_capsize,alpha=error_alpha,zorder=3)
        if ri_idx==0:
            legend_handles.append(bars[0])
    if legend:
        ax.legend(handles=legend_handles,ncol=ncol,prop={'size':base_fontsize-3.5})
    check_ax_detail(ax,ax_label,xlabel,ylabel,yticks,yscale,yticklabels,
                   ylim,xticks,xscale,xticklabels,xlim,base_fontsize,
                   ylabelpad=ylabelpad,label_loc=label_loc) 

def plot_corr_mean_varying(ax,ax_label,filename,chosen_dict,xname,method_list,label_list,xlabel,ylabel,markersize,markeredgewidth,colors,base_fontsize,yscale,yticks=[],yticklabels=[],ylim=[],xticks=[],xticklabels=[],xlim=[],xscale="abs",ylabelpad=0,legend=False,ncol=1,error="abs",subfigure=False,subylim=[],sub_loc=[],sub_ylabel=""):
    if len(label_list)!=len(method_list):
        raise Exception("Wrong method-label number!")
    df=pd.read_csv(filename,on_bad_lines='skip')
    if len(chosen_dict)>0:
        df=filter_data(df,chosen_dict) 
    if error=="abs": 
        for method in method_list:
            df[method]=np.abs(df["ideal"]-df[method])  
    else: 
        for method in method_list:
            df[method]=np.log(np.abs(df["ideal"]-df[method])/np.abs(df["ideal"])+1) 
    for i,method in enumerate(method_list):
        sns.lineplot(data=df,x=xname,y=method,label=label_list[i],ax=ax,color=colors[method],markers=True,marker="o",markersize=markersize,markeredgewidth=markeredgewidth,markeredgecolor='gray',legend=False)
    
    if subfigure:
        axins=ax.inset_axes(sub_loc) 
        errors=np.mean([df[method].values for method in method_list],axis=1)
        bars=axins.bar(range(len(method_list)),errors,color=[colors[name] for name in method_list],alpha=0.9)
        for bar in bars:
            yval=bar.get_height()
            axins.text(bar.get_x()+bar.get_width()/2,yval,round(yval*100,1),ha='center',va='bottom',fontsize=base_fontsize-6)
        axins.set_xticks([])
        axins.set_xticklabels([])
        axins.set_yticks([])
        axins.set_yticklabels([])
        axins.set_ylim(*subylim)
        axins.set_ylabel(sub_ylabel,fontsize=base_fontsize-6)
    if legend:
        ax.legend(ncol=ncol,prop={'size':base_fontsize-3.5})
    check_ax_detail(ax,ax_label,xlabel,ylabel,yticks,yscale,yticklabels,ylim,xticks,xscale,xticklabels,xlim,base_fontsize,ylabelpad=ylabelpad)
def random_MER_ind(qn,measure_error,std,seed=1,max_retries=1,data_qubit_scale=1,max_qn=20):
    #新增：还需要生成只对data qubits的error进行缩放的meausure分布，只在最后进行微调。
    dq_indices=list(range(qn)) 
    rnd=np.random.RandomState(seed)
    rates=rnd.normal(measure_error,std,max_qn)
    rates=rates[:qn]
    retries=0
    while np.any(rates<0) and retries<max_retries:
        negative_indices=np.where(rates<0)[0]
        new_rates=rnd.normal(measure_error,std,len(negative_indices))
        rates[negative_indices]=new_rates
        retries+=1
    rates[rates<0]=0
    measure_error_dict=dict(zip(dq_indices,rates))
    if (data_qubit_scale>0) and data_qubit_scale!=1: 
        for dq in dq_indices:
            measure_error_dict[dq]=measure_error_dict[dq]*data_qubit_scale
    return measure_error_dict 
def get_list(ls):
    n_ls=[]
    for row in ls:
        row=str(row)
        row=row.strip('[]')
        row=row.replace('array([','')
        row=row.replace('])','')
        row=row.replace('np.float64(','')
        row=row.replace(')','')
        row=row.split(',')
        row=list(map(float,row))
        n_ls.append(row)
    return np.array(n_ls)
#ANCHOR --loc
def plot_loc_comp(ax,ax_label,filename,chosen_dict,method_list,label_list,depth_list,xlabel,ylabel,colors_dict,base_fontsize,yscale,yticks=[],yticklabels=[],ylim=[],xlim=[],ylabelpad=0,error="abs",xlabelpad=0,width=0.3,xticks=[],xscale="abs",xticklabels=[],bar_alpha=1):
    df=pd.read_csv(filename,on_bad_lines='skip')
    if len(chosen_dict)>0:
        df=filter_data(df,chosen_dict) 
    if error=="abs":
        for method in method_list:
            df[method]=np.abs(df["ideal"]-df[method]) 
    elif error=="relative":
        for method in method_list:
            df[method]=np.log(np.abs(df["ideal"]-df[method])/np.abs(df["ideal"])+1)
    mean_values=[]
    std_values=[]
    num=len(df)
    bar_colors=[]
    for method in method_list:
        mean_values.append(np.mean(df[method].values))
        std_values.append(np.std(df[method].values)/np.sqrt(num))
        bar_colors.append(colors_dict[method])
    bars = ax.bar(depth_list, mean_values, yerr=std_values,
              color=bar_colors,capsize=2,ecolor='gray',alpha=bar_alpha,edgecolor="white",width=width)
    check_ax_detail(ax,ax_label,xlabel,ylabel,yticks,yscale,yticklabels,ylim,xticks,xscale,xticklabels,xlim,base_fontsize,ylabelpad=ylabelpad,xlabelpad=xlabelpad)

# def plot_loc_comp(ax,ax_label,filename,chosen_dict,method_list,label_list,xlabel,ylabel,color_list,ri_list,base_fontsize,yscale,yticks=[],yticklabels=[],ylim=[],xlim=[],ylabelpad=0,error="abs",xlabelpad=0,width=0.3,xticks=[],xscale="abs",xticklabels=[],bar_alpha=0.8):
#     if len(label_list)!=len(method_list):
#         raise Exception("Wrong method-label number!")
#     df=pd.read_csv(filename,on_bad_lines='skip')
#     if len(chosen_dict)>0:
#         df=filter_data(df,chosen_dict) 
#     df["MS"]=get_list(df["MS"].values)
#     if error=="abs":
#         df["MS"]=df.apply(lambda row:np.abs(row['MS']-row['ideal']),axis=1)   
#         for method in method_list:
#             df[method]=np.abs(df["ideal"]-df[method])  
#     elif error=="relative":
#         df["MS"]=df.apply(lambda row:np.log(np.abs(row['MS']-row["ideal"])/np.abs(row["ideal"])+1), axis=1) 
#         for method in method_list:
#             df[method]=np.log(np.abs(df["ideal"]-df[method])/np.abs(df["ideal"])+1)
#     df["MS_mean"]=df["MS"].apply(lambda x:np.mean(x)) 
#     num=int(len(df)/3)
#     grouped=df.groupby('ri').agg(MS_mean_mean=('MS_mean','mean'),MS_mean_se=('MS_mean', lambda x: x.std()/np.sqrt(num)),MS_lg_mean=('MS_lg','mean'),MS_lg_se=('MS_lg',lambda x:x.std()/np.sqrt(num)),noisy_MF_mean=('noisy_MF','mean'),noisy_MF_se=('noisy_MF',lambda x:x.std()/np.sqrt(num))).reset_index() 

#     grouped['ri']=pd.Categorical(grouped['ri'],categories=ri_list,ordered=True)
#     grouped=grouped.sort_values('ri') 
#     x_positions=np.arange(len(ri_list))
    
#     ax.bar(x_positions-width-0.05,grouped['noisy_MF_mean'],width=width,color=color_list[0],label='noisy_MF',yerr=grouped['noisy_MF_se'],capsize=2,ecolor='gray',alpha=bar_alpha,edgecolor="white")
#     ax.bar(x_positions,grouped['MS_mean_mean'],width=width,color=color_list[1],label='MS_mean',yerr=grouped['MS_mean_se'],capsize=2,ecolor='gray',alpha=bar_alpha,edgecolor="white")
#     ax.bar(x_positions+width+0.05,grouped['MS_lg_mean'],width=width,color=color_list[2],label='MS_lg',yerr=grouped['MS_lg_se'],capsize=2,ecolor='gray',alpha=bar_alpha,edgecolor="white")

#     ax.errorbar(x_positions-width-0.05,grouped['noisy_MF_mean'],yerr=grouped['noisy_MF_se'],fmt='none',ecolor='gray',elinewidth=1.2,capsize=1.2,alpha=1)
#     ax.errorbar(x_positions,grouped['MS_mean_mean'],yerr=grouped['MS_mean_se'],fmt='none',ecolor='gray',elinewidth=1.2,capsize=1.2,alpha=1)
#     ax.errorbar(x_positions + width+0.05,grouped['MS_lg_mean'],yerr=grouped['MS_lg_se'],fmt='none',ecolor='gray',elinewidth=1.2,capsize=1.2,alpha=1)

#     check_ax_detail(ax,ax_label,xlabel,ylabel,yticks,yscale,yticklabels,ylim,xticks,xscale,xticklabels,xlim,base_fontsize,ylabelpad=ylabelpad,xlabelpad=xlabelpad)
    
#ANCHOR-- MS-RL前置
def plot_loc_distri(fig,gs,ax_label,qn,filename,chosen_dict,method_list,label_list,xlabel,ylabel1,color_list,last_color1,last_color2,base_fontsize,yscale,yticks1=[],yticks2=[],yticklabels1=[],yticklabels2=[],ylim1=[],ylim2=[],xlim1=[],xlim2=[],ylabelpad=0,error="abs"):
    if len(label_list)!=len(method_list):
        raise Exception("Wrong method-label number!")
    df=pd.read_csv(filename,on_bad_lines='skip')
    if len(chosen_dict)>0:
        df=filter_data(df,chosen_dict) 
    # print(len(df))
    df1=df[df["ri"]==4]
    df2=df[df["ri"]==64]
    df["MS"]=df["MS"].apply(lambda x: np.array(ast.literal_eval(x)))
    df1["MS-1"]=df1["MS-1"].apply(lambda x: np.array(ast.literal_eval(x)))
    df2["MS-1"]=df2["MS-1"].apply(lambda x: np.array(ast.literal_eval(x)))
    if error=="abs":
        df["MS"]=df.apply(lambda row:np.abs(row['MS']-row['ideal']),axis=1)  
        df1["MS-1"]=df1.apply(lambda row:np.abs(row['MS-1']-row['ideal']),axis=1)
        df2["MS-1"]=df2.apply(lambda row:np.abs(row['MS-1']-row['ideal']),axis=1)
        for method in method_list:
            df[method]=np.abs(df["ideal"]-df[method])  
    elif error=="relative":
        df["MS"]=df.apply(lambda row:np.log(np.abs(row['MS']-row["ideal"])/np.abs(row["ideal"])+1), axis=1)
        df1["MS-1"]=df1.apply(lambda row:np.log(np.abs(row['MS-1']-row["ideal"])/np.abs(row["ideal"])+1), axis=1)
        df2["MS-1"]=df2.apply(lambda row:np.log(np.abs(row['MS-1']-row["ideal"])/np.abs(row["ideal"])+1), axis=1)
        for method in method_list:
            df[method]=np.log(np.abs(df["ideal"]-df[method])/np.abs(df["ideal"])+1)    
    df_ms = pd.DataFrame(df['MS'].tolist(), columns=range(qn+1))
    df_ms1 = pd.DataFrame(df1['MS-1'].tolist(), columns=range(3))
    df_ms2 = pd.DataFrame(df2['MS-1'].tolist(), columns=range(3))
    mean_values = df_ms.mean().tolist()  
    mean_values_1 = df_ms1.mean().tolist()  
    mean_values_2 = df_ms2.mean().tolist() 
 
    df_long = df_ms.melt(var_name='Position', value_name='Value')
    df_long1 = df_ms1.melt(var_name='Position', value_name='Value')
    df_long2 = df_ms2.melt(var_name='Position', value_name='Value')
    colors_main=[color_list[0]]*(len(mean_values)-1)+[last_color1]
    colors_sub1=[color_list[1]]*(len(mean_values_1)-1)+[last_color2]
    colors_sub2=[color_list[1]]*(len(mean_values_2)-1)+[last_color2]
    print(1,(np.mean(mean_values[:-1])-mean_values[-1])/np.mean(mean_values[:-1]))
    print("2_1",(np.min(mean_values_1[:-1])-mean_values_1[-1])/np.min(mean_values_1[:-1]))
    print("2_2",(np.mean(mean_values_2[:-1])-mean_values_2[-1])/np.mean(mean_values_2[:-1]))

    gs1=gs.subgridspec(6,2,wspace=0.06,hspace=1.8)
    ax1=fig.add_subplot(gs1[:3,:2])
    ax2=fig.add_subplot(gs1[3:,0])
    ax3=fig.add_subplot(gs1[3:,1]) 
    sns.barplot(x='Position',y='Value',data=df_long,palette=colors_main,edgecolor="lightgray",ax=ax1,capsize=0.1,legend=False,err_kws={"color": "black","alpha":.4,"linewidth":2})
    sns.barplot(x='Position',y='Value',data=df_long1,palette=colors_sub1,edgecolor="lightgray",ax=ax2,capsize=0.1,legend=False,err_kws={"color": "black","alpha":.4,"linewidth":2})
    sns.barplot(x='Position',y='Value',data=df_long2,palette=colors_sub2,edgecolor="lightgray",ax=ax3,capsize=0.1,legend=False,err_kws={"color": "black","alpha":.4,"linewidth":2}) 
 
    check_ax_detail(ax1,ax_label,xlabel,"",yticks1,yscale,yticklabels1,ylim1,range(len(mean_values)),"",[str(i) for i in range(len(mean_values)-1)]+["lg"],xlim1,base_fontsize,ylabelpad=ylabelpad)
    check_ax_detail(ax2,"",xlabel,"",yticks2,yscale,yticklabels2,ylim2,range(len(mean_values_1)),"",["0","1","lg"],xlim2,base_fontsize,ylabelpad=ylabelpad)
    check_ax_detail(ax3,"",xlabel,"",yticks2,yscale,["" for _ in range(len(yticks2))],ylim2,range(len(mean_values_1)),"",["0","1","lg"],xlim2,base_fontsize,ylabelpad=ylabelpad)
    ax2.set_ylabel(ylabel1,y=1.2,fontsize=base_fontsize,labelpad=ylabelpad)

    return ax1,ax2,ax3

def plot_corr_bar_2(ax,ax_label,qn,filename,chosen_dict,method_list,xlabel,ylabel,colors,base_fontsize,yscale,yticks=[],yticklabels=[],ylim=[],xticks=[],xticklabels=[],xlim=[],xscale="abs",ylabelpad=0,legend=False,ncol=1,error="abs",bar_alpha=0.7,width=0.3):
    df=pd.read_csv(filename,on_bad_lines='skip')
    if len(chosen_dict)>0:
        df=filter_data(df,chosen_dict)  
    df["MS"]=df["MS"].apply(lambda x: np.array(ast.literal_eval(x)))
    df["MS-1"]=df["MS-1"].apply(lambda x: np.array(ast.literal_eval(x))) 
    if error=="abs":
        df["MS"]=df.apply(lambda row:np.abs(row['MS']-row['ideal']),axis=1)  
        df["MS-1"]=df.apply(lambda row:np.abs(row['MS-1']-row['ideal']),axis=1) 
        for method in method_list:
            df[method]=np.abs(df["ideal"]-df[method])  
    elif error=="relative":
        df["MS"]=df.apply(lambda row:np.log(np.abs(row['MS']-row["ideal"])/np.abs(row["ideal"])+1), axis=1)
        df["MS-1"]=df.apply(lambda row:np.log(np.abs(row['MS-1']-row["ideal"])/np.abs(row["ideal"])+1), axis=1) 
        for method in method_list:
            df[method]=np.log(np.abs(df["ideal"]-df[method])/np.abs(df["ideal"])+1)   
    df["MS_lg"]=df["MS"].apply(lambda x: x[qn])
    df["MS_mean"] = df["MS"].apply(lambda x: np.mean(x[:qn]))
    df["MS-1_lg"]=df["MS-1"].apply(lambda x: x[2])
    df["MS-1_mean"] = df["MS-1"].apply(lambda x: np.mean(x[:2]))

    size=len(df)
    df_new=pd.DataFrame(columns=["method","value"])
    plot_list=method_list+["MS_mean","MS_lg","MS-1_mean","MS-1_lg"]
    for name in plot_list:
        df1=pd.DataFrame({"method":[name]*size,"value":df[name].values})
        df_new=pd.concat([df_new,df1],ignore_index=True) 
    sns.barplot(x='method',y='value',data=df_new,saturation=bar_alpha,palette=colors,width=width,ax=ax,errwidth=1.8,capsize=0.08,edgecolor="lightgray",err_kws={"color": "black","alpha":.5,"linewidth":10}) 
    if legend:
        ax.legend(ncol=ncol,prop={'size':base_fontsize-3.5})
    check_ax_detail(ax,ax_label,xlabel,ylabel,yticks,yscale,yticklabels,ylim,xticks,xscale,xticklabels,xlim,base_fontsize,ylabelpad=ylabelpad)


def plot_corr_MAE_3(ax,ax_label,filename,chosen_dict,method_list,xlabel,ylabel,xname,colors,base_fontsize,markersize,yscale,yticks=[],yticklabels=[],ylim=[],xticks=[],xticklabels=[],xlim=[],xscale="abs",ylabelpad=0,markeredgewidth=1,error="abs",num=4,label_loc=[-0.15,1.05],subfigure=False,subylim=[],sub_loc=[],sub_ylabel=""):
    df=pd.read_csv(filename,on_bad_lines='skip')
    if len(chosen_dict)>0:
        df=filter_data(df,chosen_dict)  
    df["MS"]=df["MS"].apply(lambda x: np.array(ast.literal_eval(x)))
    df["MS-1"]=df["MS-1"].apply(lambda x: np.array(ast.literal_eval(x))) 
    if error=="abs":
        df["MS"]=df.apply(lambda row:np.abs(row['MS']-row['ideal']),axis=1)  
        df["MS-1"]=df.apply(lambda row:np.abs(row['MS-1']-row['ideal']),axis=1) 
        for method in method_list:
            df[method]=np.abs(df["ideal"]-df[method])  
    elif error=="relative":
        df["MS"]=df.apply(lambda row:np.log(np.abs(row['MS']-row["ideal"])/np.abs(row["ideal"])+1), axis=1)
        df["MS-1"]=df.apply(lambda row:np.log(np.abs(row['MS-1']-row["ideal"])/np.abs(row["ideal"])+1), axis=1) 
        for method in method_list:
            df[method]=np.log(np.abs(df["ideal"]-df[method])/np.abs(df["ideal"])+1)   
    df["MS_lg"]=df.apply(lambda row: row["MS"][row["qn"]],axis=1)
    df["MS_mean"]=df.apply(lambda row: np.mean(row["MS"][:row["qn"]]),axis=1)
    df["MS-1_lg"]=df["MS-1"].apply(lambda x: x[2])
    df["MS-1_mean"] = df["MS-1"].apply(lambda x: np.mean(x[:2]))

    plot_list=method_list+["MS_mean","MS_lg","MS-1_mean","MS-1_lg"][:num]
    for method in plot_list:
        sns.lineplot(data=df,x=xname,y=method,ax=ax,color=colors[method],markers=True,marker="o",markersize=markersize,markeredgewidth=markeredgewidth,markeredgecolor='gray',legend=False)
    
    if subfigure:
        axins=ax.inset_axes(sub_loc)
        errors=np.mean([df[method].values for method in plot_list],axis=1) 
        bars=axins.bar(range(len(plot_list)),errors,color=[colors[name] for name in plot_list],alpha=0.9)
        for bar in bars:
            yval=bar.get_height()
            axins.text(bar.get_x()+bar.get_width()/2,yval,round(yval*10,1),ha='center',va='bottom',fontsize=base_fontsize-6)
        axins.set_xticks([])
        axins.set_xticklabels([])
        axins.set_yticks([])
        axins.set_yticklabels([])
        axins.set_ylim(*subylim)
        axins.set_ylabel(sub_ylabel,fontsize=base_fontsize-6)

    
    check_ax_detail(ax,ax_label,xlabel,ylabel,yticks,yscale,yticklabels,ylim,xticks,xscale,xticklabels,xlim,base_fontsize,ylabelpad=ylabelpad,label_loc=label_loc)